﻿using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Silverlight.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.Unity;
using Astor.Modules.DataSources.Services;
using Astor.Modules.DataSources.Screens.List;
using Microsoft.Practices.Prism.Interactivity.InteractionRequest;
using Astor.Modules.DataSources.Screens.Details;
using Moq;
using Astor.Modules.DataSources.Models;
using System.Collections.ObjectModel;

namespace Astor.Modules.DataSources.Tests.Screens.List
{
    [TestClass]
    public class DataSourceListViewModelFixture
    {
        private MockContainer _container;
        private DataSourceListViewModel _vm;
        private IDataSourcesService _service;
        private Mock<IDataSourcesService> _mockService;

        [TestInitialize]
        public void InitializeTest()
        {
            _container = new MockContainer();
            _vm = _container.Resolve<DataSourceListViewModel>();
            _service = _container.Resolve<IDataSourcesService>();
            _mockService = _container.Resolve<Mock<IDataSourcesService>>();
        }

        [TestMethod]
        public void Load()
        {
            //--given
            var dataSources = _container.Resolve<IDataSourcesService>().FindAll();

            //--when
            //ViewModel initialized data in constructor

            //--then
            Assert.IsNotNull(_vm.AddCommand);
            Assert.IsNotNull(_vm.EditCommand);
            Assert.IsNotNull(_vm.DeleteCommand);
            Assert.AreEqual(dataSources.Count(), _vm.DataSources.Count(), "DataSources are not loaded.");
        }

        [TestMethod]
        public void SelectDataSource()
        {
            //--given

            //--when
            _vm.SelectedDataSource = _vm.DataSources[0];

            //--then
            Assert.IsTrue(_vm.EditCommand.CanExecute(), "EditCommand.CanExecute must be true when DataSource selected.");
            Assert.IsTrue(_vm.DeleteCommand.CanExecute(), "DeleteCommand.CanExecute must be true when DataSource selected.");
        }

        [TestMethod]
        public void Add_Confirmed()
        {
            //--given

            //--when
            InteractionRequestedEventArgs args = null;
            _vm.DetailsRequest.Raised += (s, e) => args = e;
            _vm.AddCommand.Execute();

            var detailsVM = args.Context as DataSourceDetailsViewModel;
            detailsVM.DataSource.Name = "NewName";
            detailsVM.DataSource.Url = "NewUrl";
            detailsVM.SubmitCommand.Execute();

            args.Callback();
            
            //--then
            _mockService.Verify(m => m.Add(detailsVM.DataSource), Times.Once(), "Add must be called when confirmed");
        }

        [TestMethod]
        public void Add_NotConfirmed()
        {
            //--given

            //--when
            InteractionRequestedEventArgs args = null;
            _vm.DetailsRequest.Raised += (s, e) => args = e;
            _vm.AddCommand.Execute();

            var detailsVM = args.Context as DataSourceDetailsViewModel;
            detailsVM.Confirmed = false;

            args.Callback();

            //--then
            _mockService.Verify(m => m.Add(It.IsAny<DataSource>()), Times.Never(), 
                "Add should not be called when not confirmed.");
        }

        [TestMethod]
        public void Edit_Confirmed()
        {
            //--given

            //--when
            _vm.SelectedDataSource = _service.FindAll().First();
            InteractionRequestedEventArgs args = null;
            _vm.DetailsRequest.Raised += (s, e) => args = e;
            _vm.EditCommand.Execute();

            var detailsVM = args.Context as DataSourceDetailsViewModel;
            detailsVM.DataSource.Name = "EditedName";
            detailsVM.DataSource.Url = "EditedUrl";
            detailsVM.Confirmed = true;

            args.Callback();

            //--then
            _mockService.Verify(m => m.Modify(_vm.SelectedDataSource), Times.Once(), "Modify must be called when confirmed");
        }

        [TestMethod]
        public void Edit_NotConfirmed()
        {
            //--given

            //--when
            _vm.SelectedDataSource = _service.FindAll().First();
            InteractionRequestedEventArgs args = null;
            _vm.DetailsRequest.Raised += (s, e) => args = e;
            _vm.EditCommand.Execute();

            var detailsVM = args.Context as DataSourceDetailsViewModel;
            detailsVM.Confirmed = false;

            args.Callback();

            //--then
            _mockService.Verify(m => m.Modify(_vm.SelectedDataSource), Times.Never(), "Modify must not be called when not confirmed");
        }

        [TestMethod]
        public void Delete_Confirmed()
        {
            //--given

            //--when
            _vm.SelectedDataSource = _service.FindAll().First();
            InteractionRequestedEventArgs args = null;
            _vm.DeleteRequest.Raised += (s, e) => args = e;
            _vm.DeleteCommand.Execute();

            var confirmation = (Confirmation)args.Context;
            confirmation.Confirmed = true;

            args.Callback();

            //--then
            _mockService.Verify(m => m.Delete(_vm.SelectedDataSource), Times.Once(), "Delete must be called when confirmed.");
        }

        [TestMethod]
        public void Delete_NotConfirmed()
        {
            //--given

            //--when
            _vm.SelectedDataSource = _service.FindAll().First();
            InteractionRequestedEventArgs args = null;
            _vm.DeleteRequest.Raised += (s, e) => args = e;
            _vm.DeleteCommand.Execute();

            var confirmation = (Confirmation)args.Context;
            confirmation.Confirmed = false;

            args.Callback();

            //--then
            _mockService.Verify(m => m.Delete(_vm.SelectedDataSource), Times.Never(), "Delete must not be called when not confirmed.");
        }

    }
}